/*
* Copyright (c) 2024 China Unicom Digital Technology Co., Ltd.
* openFuyao is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
*          http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
* Author: YuXiang Guo
* Date: 2024-11-25
 */

package beresource

import (
	"reflect"
	"testing"

	"k8s.io/utils/pointer"

	"openfuyao.com/colocation-management/pkg/colocation-overquota-agent/nriserver/core"
	"openfuyao.com/colocation-management/pkg/common"
	"openfuyao.com/colocation-management/pkg/utils"
)

// TestSetBEPodResources
func TestSetBEPodResources(t *testing.T) {
	_, _, marshal := core.SetupTest(t)

	info := createPodInfo(marshal)

	expect := core.PodInfo{
		PodResponese: core.PodResponse{
			Resources: utils.LinuxContainerResources{
				CPUShares:   pointer.Int64(2048),
				CFSQuota:    pointer.Int64(200000),
				MemoryLimit: pointer.Int64(2147483648),
			},
		},
	}
	err := NewBEResourceRunner().SetPodResources(&info)
	if err != nil {
		t.Errorf("SetPodResources failed,err:%v", err)
	}

	if !reflect.DeepEqual(*info.PodResponese.Resources.CPUShares, *expect.PodResponese.Resources.CPUShares) {
		t.Errorf("Expected  to be %v, got %v", *expect.PodResponese.Resources.CPUShares,
			*info.PodResponese.Resources.CPUShares)
	}
	if !reflect.DeepEqual(*info.PodResponese.Resources.CFSQuota, *expect.PodResponese.Resources.CFSQuota) {
		t.Errorf("Expected  to be %v, got %v", *expect.PodResponese.Resources.CFSQuota,
			*info.PodResponese.Resources.CFSQuota)
	}
	if !reflect.DeepEqual(*info.PodResponese.Resources.CPUShares, *expect.PodResponese.Resources.CPUShares) {
		t.Errorf("Expected  to be %v, got %v", *expect.PodResponese.Resources.MemoryLimit,
			*info.PodResponese.Resources.MemoryLimit)
	}

}

// TestSetBEPodCPUShares
func TestSetBEPodCPUShares(t *testing.T) {
	_, _, marshal := core.SetupTest(t)

	info := createPodInfo(marshal)

	expect := core.PodInfo{
		PodResponese: core.PodResponse{
			Resources: utils.LinuxContainerResources{
				CPUShares: pointer.Int64(2048),
			},
		},
	}

	err := NewBEResourceRunner().SetPodCPUShares(&info)
	if err != nil {
		t.Errorf("SetPodResources failed,err:%v", err)
	}
	if !reflect.DeepEqual(*info.PodResponese.Resources.CPUShares, *expect.PodResponese.Resources.CPUShares) {
		t.Errorf("Expected  to be %v, got %v", *expect.PodResponese.Resources.CPUShares,
			*info.PodResponese.Resources.CPUShares)
	}
}

func TestSetBEPodMemoryLimit(t *testing.T) {

	_, _, marshal := core.SetupTest(t)

	info := createPodInfo(marshal)

	expect := core.PodInfo{
		PodResponese: core.PodResponse{
			Resources: utils.LinuxContainerResources{
				MemoryLimit: pointer.Int64(2147483648),
			},
		},
	}
	err := NewBEResourceRunner().SetPodMemoryLimit(&info)
	if err != nil {
		t.Errorf("SetPodResources failed,err:%v", err)
	}

	if !reflect.DeepEqual(*info.PodResponese.Resources.MemoryLimit, *expect.PodResponese.Resources.MemoryLimit) {
		t.Errorf("Expected  to be %v, got %v", *expect.PodResponese.Resources.MemoryLimit,
			*info.PodResponese.Resources.MemoryLimit)
	}
}

// TestSetBEPodCFSQuota
func TestSetBEPodCFSQuota(t *testing.T) {
	_, _, marshal := core.SetupTest(t)

	info := createPodInfo(marshal)

	expect := core.PodInfo{
		PodResponese: core.PodResponse{
			Resources: utils.LinuxContainerResources{
				CFSQuota: pointer.Int64(200000),
			},
		},
	}

	err := NewBEResourceRunner().SetPodCFSQuota(&info)
	if err != nil {
		t.Errorf("SetPodResources failed,err:%v", err)
	}
	if !reflect.DeepEqual(*info.PodResponese.Resources.CFSQuota, *expect.PodResponese.Resources.CFSQuota) {
		t.Errorf("Expected  to be %v, got %v", *expect.PodResponese.Resources.CFSQuota,
			*info.PodResponese.Resources.CFSQuota)
	}
}

// TestSetBEContainerResources
func TestSetBEContainerResources(t *testing.T) {

	_, _, marshal := core.SetupTest(t)

	info := createContainerInfo(marshal)

	expect := core.ContainerInfo{
		ContainerResponese: core.ContainerResponse{
			Resources: utils.LinuxContainerResources{
				CPUShares:   pointer.Int64(2048),
				CFSQuota:    pointer.Int64(200000),
				MemoryLimit: pointer.Int64(2147483648),
			},
		},
	}

	err := NewBEResourceRunner().SetContainerResources(&info)
	if err != nil {
		t.Errorf("SetContainerResources failed,err:%v", err)
	}
	if !reflect.DeepEqual(*info.ContainerResponese.Resources.CPUShares, *expect.ContainerResponese.Resources.CPUShares) {
		t.Errorf("Expected  to be %v, got %v", *expect.ContainerResponese.Resources.CPUShares,
			*info.ContainerResponese.Resources.CPUShares)
	}
	if !reflect.DeepEqual(*info.ContainerResponese.Resources.CFSQuota, *expect.ContainerResponese.Resources.CFSQuota) {
		t.Errorf("Expected  to be %v, got %v", *expect.ContainerResponese.Resources.CFSQuota,
			*info.ContainerResponese.Resources.CFSQuota)
	}
	if !reflect.DeepEqual(*info.ContainerResponese.Resources.MemoryLimit,
		*expect.ContainerResponese.Resources.MemoryLimit) {
		t.Errorf("Expected  to be %v, got %v", *expect.ContainerResponese.Resources.MemoryLimit,
			*info.ContainerResponese.Resources.MemoryLimit)
	}
}

// TestSetBEContainerCPUShares
func TestSetBEContainerCPUShares(t *testing.T) {
	_, _, marshal := core.SetupTest(t)

	info := createContainerInfo(marshal)

	expect := core.ContainerInfo{
		ContainerResponese: core.ContainerResponse{
			Resources: utils.LinuxContainerResources{
				CPUShares: pointer.Int64(2048),
			},
		},
	}

	err := NewBEResourceRunner().SetContainerCPUShares(&info)
	if err != nil {
		t.Errorf("SetContainerCPUShares failed,err:%v", err)
	}
	if !reflect.DeepEqual(*info.ContainerResponese.Resources.CPUShares, *expect.ContainerResponese.Resources.CPUShares) {
		t.Errorf("Expected  to be %v, got %v", *expect.ContainerResponese.Resources.CPUShares,
			*info.ContainerResponese.Resources.CPUShares)
	}
}

// TestSetBEContainerMemoryLimit
func TestSetBEContainerMemoryLimit(t *testing.T) {
	_, _, marshal := core.SetupTest(t)

	info := createContainerInfo(marshal)

	expect := core.ContainerInfo{
		ContainerResponese: core.ContainerResponse{
			Resources: utils.LinuxContainerResources{
				MemoryLimit: pointer.Int64(2147483648),
			},
		},
	}

	err := NewBEResourceRunner().SetContainerMemoryLimit(&info)
	if err != nil {
		t.Errorf("SetContainerMemoryLimit failed,err:%v", err)
	}
	if !reflect.DeepEqual(*info.ContainerResponese.Resources.MemoryLimit,
		*expect.ContainerResponese.Resources.MemoryLimit) {
		t.Errorf("Expected  to be %v, got %v", *expect.ContainerResponese.Resources.MemoryLimit,
			*info.ContainerResponese.Resources.MemoryLimit)
	}
}

// TestSetBEContainerCFSQuota
func TestSetBEContainerCFSQuota(t *testing.T) {
	_, _, marshal := core.SetupTest(t)

	info := createContainerInfo(marshal)

	expect := core.ContainerInfo{
		ContainerResponese: core.ContainerResponse{
			Resources: utils.LinuxContainerResources{
				CFSQuota: pointer.Int64(200000),
			},
		},
	}

	err := NewBEResourceRunner().SetContainerCFSQuota(&info)
	if err != nil {
		t.Errorf("SetContainerCFSQuota failed,err:%v", err)
	}
	if !reflect.DeepEqual(*info.ContainerResponese.Resources.CFSQuota,
		*expect.ContainerResponese.Resources.CFSQuota) {
		t.Errorf("Expected  to be %v, got %v", *expect.ContainerResponese.Resources.CFSQuota,
			*info.ContainerResponese.Resources.CFSQuota)
	}

}

func createPodSandboxConfig(qosClass string, marshal []byte) utils.PodSandboxConfig {
	return utils.PodSandboxConfig{
		Annotations: map[string]string{
			common.QosClassAnnotationKey:                   qosClass,
			common.ExtenderResourceConfigurationAnnotation: string(marshal),
		},
	}
}

func createPodInfo(marshal []byte) core.PodInfo {
	info := core.PodInfo{
		PodRequest: core.PodRequest{
			PodSandboxConfig: createPodSandboxConfig("BE", marshal),
		},
	}
	return info
}

func createContainerInfo(marshal []byte) core.ContainerInfo {
	info := core.ContainerInfo{
		ContainerRequest: core.ContainerRequest{
			ContainerMeta: core.ContainerMetadata{
				Name: "container1",
			},
			PodSandboxConfig: createPodSandboxConfig("BE", marshal),
		},
	}
	return info
}
